//Author: Austen Higgins-Cassidy
// 4/10/2012
#include "extractor.h"

unsigned int htoi (const char *ptr, unsigned int len)
{
	//ADDITIONALLY DETECTS BASE-10 NUMBERS
unsigned int value = 0;
unsigned short i = 0;
while (ptr[0] == ' ' || ptr[0] == '\t'){
	++ptr;
	++i;
}
//Tolerate 0x
if(ptr[0] == '0' && ptr[1] == 'x'){
	++ptr;++ptr;i+=2;
}else return atoi(ptr); //We are not correctly formatted as a hex number! base10!
    while(i < len) {
        if (ptr[0] >= '0' && ptr[0] <= '9')
            value = (value << 4) + (ptr[0] - '0');
        else if (ptr[0] >= 'A' && ptr[0] <= 'F')
            value = (value << 4) + (ptr[0] - 'A' + 10);
        else if (ptr[0] >= 'a' && ptr[0] <= 'f')
            value = (value << 4) + (ptr[0] - 'a' + 10);
        else
            return value;
        (++ptr);
    }
}

unsigned int shtoi(std::string hex){
	return htoi(hex.c_str(), hex.length());
}

void chompL(std::string &str){
	//Remove all whitespace until a non whitespace character is left
	if(str == "")
		return;
	if(str[0] == '\0')
		return;
	for(int i = 0; i < str.length(); ++i){
		if(str[i] <= 32)
			continue;
		else
		{
			str = str.substr(i);
			return;
		}
	}
}

void chompR(std::string &str){
	if(str == "")
		return;
	if(str[str.length()-1] == '\0')
		return;
	for(int i = str.length()-1; i > 0; --i){
		if(str[i] <= 32)
			continue;
		else
		{
			str = str.substr(0,i+1);
			return;
		}
	}

}

void chomp(std::string &str){
	chompL(str);
	chompR(str);
}

int extractUntil(std::istream &file, std::string &buffer, std::string delims){
	char buf;
	while(file.get(buf).good()){
		for(int i = 0; i < delims.length(); ++i)
			if(buf == delims[i])
				return i;
		buffer += buf;
	}
	return -1;
}

int extractUntilNOT(std::istream &file, std::string &buffer, std::string delims){
	char buf;
	while(file.get(buf).good()){
		for(int i = 0; i < delims.length(); ++i)
			if(buf != delims[i])
				return i;
		buffer += buf;
	}
	return -1;
}

char leftShift(char *target, char in, int size){
	char buf = target[0];
	for(int i = 1; i < size; ++i){
		target[i-1] = target[i];
	}
	target[size-1] = in;
	return buf;
}

int extractUntilToken(std::istream &file, std::string &buffer, std::string token){
	//Chomp the token too
	char *buf;
	char c;
	buf = new char[token.length()+1];
	//int pos = file.tellg();
	//file.get(buf, token.length()); 
	file.read(buf, sizeof(char)*token.length());
	buf[token.length()] = '\0';
	while(file.get(c).good()){
			if(token.compare(buf) == 0){
				//pos = file.tellg();
				//pos -= token.length();
				//file.seekg(pos);
				delete [] buf;
				return 1;
			}
			//buffer += buf[0];
			buffer += leftShift(buf, c, token.length());
			//buf[token.length()-1] << c;
	}
	delete [] buf;
	return -1;
}



int extractUntilTokenList(std::istream &file, std::string &buffer, std::string tokenlist[], int tokens, std::string *token_match){
	char *buf;
	char c;
	
	int begin = file.tellg();
	int t_len = 0;
	//int tokens = dimsize(tokenlist);
	for(int i = 0; i < tokens; ++i){
		if(tokenlist[i].length() > t_len)
			t_len = tokenlist[i].length();
	}
	buf = new char[t_len];
	for(int x = 0; x < t_len; ++x)
		if(!file.get(buf[x]).good())
			buf[x] = ' ';

	//Initial token search
	
	//file.read(buf, sizeof(char)*t_len);

	for(int i = 0; i < tokens; ++i){
		for(int k = 0; k <= (t_len - tokenlist[i].length()); ++k){
			//Linear substring search
			if(tokenlist[i].compare(0, tokenlist[i].length(), buf,k, tokenlist[i].length()) == 0){
				if(token_match != NULL)
					*token_match = tokenlist[i];
				for(int j = 0; j < k; ++j) //Copy the required characters out
					buffer += leftShift(buf, ' ', t_len);
				//Move to the end of the token
				int pos = -(sizeof(char)*(t_len - (k+tokenlist[i].length())));
				file.seekg(pos,std::ios::cur);
				delete [] buf;
				return i;
			}
		}
	}
	//We have searched the initial string, now all we need to do is constantly check the end
	while(file.get(c).good()){
		buffer += leftShift(buf, c, t_len);
		for(int i = 0; i < tokens; ++i){
			if(tokenlist[i].compare(0, tokenlist[i].length(), buf, t_len-tokenlist[i].length(), tokenlist[i].length()) == 0){
				if(token_match != NULL)
					*token_match = tokenlist[i];
				//Since we are reading one character at a time, we only need to save the offset
				for(int j = 0; j < t_len-tokenlist[i].length(); ++j)
					buffer += leftShift(buf, ' ', t_len);
				//No seeking required
				delete [] buf;
				return i;
			}
		}
		
	}
	//Bailout
	for(int j = 0; j < t_len; ++j)
					buffer += leftShift(buf, ' ', t_len);
	delete [] buf;
	return -1;

}